/**
 * Project 68th
 */


#ifndef _EVENTLOOP_H
#define _EVENTLOOP_H

#include "Acceptor.h"
#include "TcpConnection.h"
#include <sys/epoll.h>
#include <vector>
#include <map>
#include <mutex>
using std::vector;
using std::map;
using std::mutex;
using std::lock_guard;

using Functor = function<void()>;

class EventLoop {
public: 
    /**
     * @param acceptor
     */
    EventLoop(Acceptor & acceptor);
    ~EventLoop();

    //事件循环的控制
    void loop();
    void unloop();

    void setNewConnectionCallback(TcpConnectionCallback && cb);
    void setMessageCallback(TcpConnectionCallback && cb);
    void setCloseCallback(TcpConnectionCallback && cb);

    
    //初始化计数器
    int createEventFd();

    //对计数器进行读操作
    void handleRead();

    //对计数器进行写操作
    void wakeup();

    //往接受区放入希望主线程做的任务
    void runInLoop(Functor && cb);

    //执行任务
    void doPendingFunctor();


private:
    //创建代表epoll的文件描述符
    int createEpollFd();

    //将某一个文件描述符放到红黑树上监听
    void addEpollReadFd(int fd);

    //从红黑树上删除某一个文件描述符，不再监听
    void delEpollReadFd(int fd);

    //封装了epoll_wait
    void waitEpollFd();

    //listenfd就绪时，建立新的TcpConnection
    void handleNewConnection();
    
    //connfd就绪时，说明老的连接上有数据发送过来
    //进行相应的读写操作
    void handleMessage(int fd);
private: 
    int _epfd;//epoll
    vector<struct epoll_event> _evtList;//就绪列表
    bool _isLooping;//事件循环标志位
    Acceptor & _acceptor; //要用到accept函数
    map<int, shared_ptr<TcpConnection>> _conns; //存储连接信息
    
    TcpConnectionCallback _onNewConnection;
    TcpConnectionCallback _onMessage;
    TcpConnectionCallback _onClose;

    int _evtfd;
    vector<Functor> _pendings;
    mutex _mutex;
};

#endif //_EVENTLOOP_H
